package model;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
public class Rechnung implements IEntity {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private long id;
	private double preis; // this can also be calculated via belegung.
	@Temporal(TemporalType.TIMESTAMP)
	private Date datum = new Date();
	private String reason;
	@OneToOne(mappedBy = "rechnung", cascade = CascadeType.PERSIST)
	private Reservierung reservierung;
	@ManyToOne(cascade = CascadeType.PERSIST)
	private Kunde payingCustomer;

	public Rechnung() {

	}

	public Rechnung(Reservierung res) {
		this.reservierung = res;
		if (this.reservierung != null)
			this.reservierung.setRechnung(this);
	}

	public Kunde getPayingCustomer() {
		return payingCustomer;
	}

	public void setPayingCustomer(Kunde payingCustomer) {
		this.payingCustomer = payingCustomer;
	}

	public double getPreis() {
		return preis;
	}

	public Date getDatum() {
		return datum;
	}

	public void setDatum(Date datum) {
		this.datum = datum;
	}

	public String getReason() {
		return reason;
	}

	public Reservierung getReservierung() {
		return reservierung;
	}

	// ##################################################################
	// ======================== Business Logic ==========================

	/**
	 * Calcualtes the price for this Rechnung
	 */
	public void calculatePreis() {
		String textDetails = "";
		for (Belegung b : this.reservierung.getBelegungen()) {
			RoomforRecipe r = new RoomforRecipe();
			double roomTotal = 0.0;
			r.room = b.getZimmer();
		
			
			r.highestDiscount = payingCustomer != null ? payingCustomer.getRabat() : 0;
			
			// int[] c = Kunde.getNumerOfAdultsAndChildren(b.getKunden());
			r.nrOfAdults = b.nrOfAdults();
			r.nrOfChildren = b.nrOfChildren();
			double roomAmount = 0.0;
			String rt = "Invalid Booking for room!: Adults: " + r.nrOfAdults
					+ " Children: " + r.nrOfChildren;
			System.out.println("Debug calc price, Adults:" + r.nrOfAdults
					+ "Children: " + r.nrOfChildren);
			if (r.nrOfAdults == 1) {
				if (r.nrOfChildren == 0) {
					roomAmount = r.room.getPreisEZ();
					rt = "Single room";
				} else if (r.nrOfChildren == 1) {
					roomAmount = r.room.getPreisEZmitKind();
					rt = "Singel room with child";
				} else if (r.nrOfChildren == 2) {
					roomAmount = r.room.getPreisEZmitZweiKindern();
					rt = "Single room with two children";
				}
			} else if (r.nrOfAdults == 2) {
				if (r.nrOfChildren == 0) {
					roomAmount = r.room.getPreisDZ();
					rt = "Double room";
				} else if (r.nrOfChildren == 1) {
					roomAmount = r.room.getDZMitKind();
					rt = "Double room with child";
				}
			} else {
				roomAmount = r.room.getPreisDreifachbelegung();
				rt = "Double room with extra bed";
			}
			
			Date until = reservierung.getBis();
			// check if this is early departure
			if(datum.before(until) && datum.after(reservierung.getVon())){
				// only calulate the nights which the customer actually stayed!
				until = datum;
			}
			
			int nights = (int) Math.abs(((until.getTime() - reservierung
					.getVon().getTime()) / (1000 * 60 * 60 * 24)) );

			roomTotal = roomAmount * nights;
			
			textDetails += "Room: " + b.getZimmer().getName() + "   " + rt
					+ "   per Night: " + roomAmount + "€   "
					 + " nights: " + nights + " subtotal: " + roomTotal +"€ \n";
			preis += roomTotal;
		}
		preis = preis * (1.0 - (reservierung.getRabatt() / 100.0));
		reason = textDetails;
	}

	// ##################################################################
	// ================== Setters and getters start =====================

	public void setReservierung(Reservierung reservierung) {
		this.reservierung = reservierung;
	}

	private class RoomforRecipe {
		public Zimmer room;
		public int nrOfAdults;
		public int nrOfChildren;
		public List<Kunde> customers;
		public double highestDiscount;
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}
}
